/*************************************************************
*
* m3d_noise.h
*
* Noise support functions
*************************************************************/

#ifndef _M3D_NOISE_H_
#define _M3D_NOISE_H_

enum {
   M3D_NOISE_TYPE_GRAD           = 0,   // gradient noise
   M3D_NOISE_TYPE_VALUE,                // 
   M3D_NOISE_TYPE_VALUE_CONV,           // 
   M3D_NOISE_TYPE_SPARSE_CONV,          // 
   M3D_NOISE_TYPE_MAX,
};

//
// Abstract noise class
//
class m3dNOISE {
protected:
   int     type;         // NOISE_TYPE...
   int     size;         // table size
   int     cellSize;     // size of noise cell
   void   *table;        // noise table
   int    *tabHash;      // random permutation [0,..,size-1] -> [0,..,size-1]

   m3dNOISE          (int _type, int _cellSize, int _size) : type(_type), size(_size), cellSize(_cellSize), table(NULL), tabHash(NULL) {}
public:
   virtual ~m3dNOISE (void);
   
   virtual BOOL   Fill       (int seed);
   virtual float  GetValue   (m3dV *pPos) = 0;

protected:
   void*          operator[] (int cellInd) { ASSERT(table && cellInd >= 0 && cellInd < size); return (void*)(((BYTE*)table) + cellInd*cellSize); }
};
//
// Prototype for value noises
//
class m3dNOISE_VALUE_PROTO : public m3dNOISE {
public:
   m3dNOISE_VALUE_PROTO (int _type, int _size) : m3dNOISE(_type, sizeof(float), _size)  {}

   virtual BOOL   Fill       (int seed);
};

//
// Gradient noise
//
class m3dNOISE_GRAD : public m3dNOISE {
public:
   m3dNOISE_GRAD (int _size) : m3dNOISE(M3D_NOISE_TYPE_GRAD, sizeof(m3dV), _size)  {}

   virtual BOOL   Fill       (int seed);
   virtual float  GetValue   (m3dV *pPos);
};

//
// Value noise
//
class m3dNOISE_VALUE : public m3dNOISE_VALUE_PROTO {
public:
   m3dNOISE_VALUE (int _size) : m3dNOISE_VALUE_PROTO(M3D_NOISE_TYPE_VALUE, _size)  {}

   virtual float  GetValue   (m3dV *pPos);
};

//
// Value-convolution noise
//
class m3dNOISE_VALUE_CONV : public m3dNOISE_VALUE_PROTO {
public:
   m3dNOISE_VALUE_CONV (int _size) : m3dNOISE_VALUE_PROTO(M3D_NOISE_TYPE_VALUE_CONV, _size)  {}

   virtual float  GetValue   (m3dV *pPos);
};

//
// Sparse-convolution noise
//
class m3dNOISE_SPARSE_CONV : public m3dNOISE {
public:
   m3dNOISE_SPARSE_CONV (int _size) : m3dNOISE(M3D_NOISE_TYPE_SPARSE_CONV, 4*sizeof(float), _size)  {}

   virtual BOOL   Fill       (int seed);
   virtual float  GetValue   (m3dV *pPos);
};

//
// Functions
//
extern BOOL m3dInitNoise  (void);
extern void m3dTermNoise  (void);

//
// Global variables
//
extern m3dNOISE      *m3dNoise;

#endif // _M3D_NOISE_H_

//
// End of file m3d_noise.h
//
